package org.chronologger.poppaea.client.widgets;

import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.ui.AbsolutePanel;
import com.google.gwt.user.client.ui.PopupPanel;

public class ArrowPopupPanel extends PopupPanel {

	public static final int ARROW_HEIGHT = 23;
	public static final int ARROW_WIDTH = 11;
	public static final int MARGIN_WIDTH = 1 + ARROW_WIDTH;
	public static final int MARGIN_HEIGHT = 2;
	public static final int ARROW_TIP_OFFSET = ARROW_HEIGHT / 2;
	public static final int CORNER_OFFSET = 5;
	public static final int AESTHETIC_ARROW_TIP_Y = 30;
	
	public static enum Orientation {
		left, right
	};

	private final EventAwareAbsolutePanel mainPanel = new EventAwareAbsolutePanel();
	private final EventAwareAbsolutePanel contentPanel = new EventAwareAbsolutePanel();
	protected final AbsolutePanel arrow = new AbsolutePanel();
	private Orientation orientation;

	public ArrowPopupPanel() {
		super(true);
		
		setWidget(mainPanel);
		mainPanel.setStyleName("popup-panel");
		mainPanel.setSize("100%", "100%");
		mainPanel.add(contentPanel);
		mainPanel.add(arrow, 0, 30);
		getContentPanel().setStyleName("popup-panel-content");
		this.orientation = Orientation.left;
		arrow.setStyleName("popup-panel-arrow-" + orientation.toString());		
	}
	
	/**
	 * sets y position of arrow tip, relative to top of panel.
	 * 
	 * @param y
	 */
	public void setArrowPosition(final int y) {
		int left = mainPanel.getWidgetLeft(arrow);
		if(y < CORNER_OFFSET + ARROW_TIP_OFFSET)
			mainPanel.setWidgetPosition(arrow, left, CORNER_OFFSET);
		else
			mainPanel.setWidgetPosition(arrow, left, y - ARROW_HEIGHT / 2);
	}

	/**
	 * 
	 * @param xleft
	 * @param xright
	 * @param y
	 * @param contentwidth
	 * @param contentheight
	 * @return
	 */
	protected void pointAt(int xleft, int xright, int y,
			int contentWidth, int contentHeight) {
		int height = Window.getClientHeight();
		int width = Window.getClientWidth();
		
		// number of free pixels if we place the panel on the left
		int leftscore = xleft - MARGIN_WIDTH - contentWidth;
		// number of free pixels if we place the panel on the right
		int rightscore = width - xright - MARGIN_WIDTH - contentWidth;
		
		// prefer the right side (haha)
		Orientation orientation = rightscore < 10 ? Orientation.right : Orientation.left;
		
		// calculate top. We prefer putting the label below the point.
		int top = y - AESTHETIC_ARROW_TIP_Y;
		int arrowTip = AESTHETIC_ARROW_TIP_Y;
		if(top + contentHeight + MARGIN_HEIGHT > height) {
			top = height - contentHeight - MARGIN_HEIGHT;
			arrowTip = y - top;
		}
		
		if(orientation == Orientation.right) {
			setPopupPosition(leftscore, top);
		} else {
			setPopupPosition(xright, top);
		}
		
		show();
		setOrientation(orientation);
		setSize(contentWidth + MARGIN_WIDTH + "px", contentHeight + MARGIN_HEIGHT + "px");
		setArrowPosition(arrowTip);
	}

	@Override
	public void setWidth(String width) {
		super.setWidth(width);
		
		int w = getOffsetWidth() - 12;
		if(w > 0) {
			getContentPanel().setWidth(w + "px");
			if (orientation == Orientation.right) {
				mainPanel.setWidgetPosition(arrow, w+1, 30);
			}
		}
	}

	@Override
	public void setHeight(String height) {
		super.setHeight(height);
		int h = getOffsetHeight() - 2;
		if(h > 0)
			getContentPanel().setHeight(h + "px");
	}

	public EventAwareAbsolutePanel getContentPanel() {
		return contentPanel;
	}

	public void setOrientation(Orientation orientation) {
		this.orientation = orientation;
		
		switch (orientation) {
		case left:
			mainPanel.setWidgetPosition(getContentPanel(), ARROW_WIDTH - 1, 0);
			break;
		case right:
			mainPanel.setWidgetPosition(getContentPanel(), 0, 0);
			break;
		}
		
		arrow.setStyleName("popup-panel-arrow-" + orientation.toString());	
		mainPanel.setWidgetPosition(arrow, orientation == Orientation.left ? 0 : mainPanel.getOffsetWidth() - ARROW_WIDTH, 0);
		
		// update the arrow position
		setWidth(getOffsetWidth()+"px");
	}

	public Orientation getOrientation() {
		return orientation;
	}

}
